package eastmoney

import (
	"io/ioutil"
	"net/http"
	"strconv"

	"gitee.com/lenchu/stock-api-go/api"
	"gitee.com/lenchu/stock-api-go/utils"

	"github.com/gookit/goutil/arrutil"
	"github.com/tidwall/gjson"
)

type StockService struct {
	Client      *http.Client
	tokenKeeper utils.ObjectKeeper[string]
}

func (this *StockService) GetByCode(code string) *api.Stock {
	codes := []string{code}
	resultMap := this.BatchGetByCode(codes)
	return resultMap[code]
}
func (this *StockService) SearchStock(keyword string) []*api.Stock {
	searchUrl := search_url + keyword
	resp, err := this.getWithRetry(searchUrl, true)
	if err != nil {
		return nil
	}
	byteBody, err := ioutil.ReadAll(resp.Body)
	strBody := string(byteBody)
	searchResultArray := gjson.Get(strBody, "QuotationCodeTable.Data").Array()
	resultList := make([]*api.Stock, len(searchResultArray))
	idx := 0
	for _, value := range searchResultArray {
		code := value.Get("Code").String()
		marketNum := value.Get("MktNum").String()
		emCode := fromCodeAndMarketNumToEastmoneyCode(code, marketNum)
		if emCode != nil {
			standardCode := emCode.getStandardCode()
			stock := api.Stock{
				Code: standardCode,
				Name: value.Get("Name").String(),
			}
			resultList[idx] = &stock
			idx++
		}
	}
	return resultList[0:idx]
}
func (this *StockService) BatchGetByCode(codes []string) map[string]*api.Stock {
	emCodes := arrutil.StringsMap(codes, func(standardCode string) string {
		emCode := fromStandardCodeToEastmoneyCode(standardCode)
		if emCode != nil {
			return emCode.getEmCode()
		}
		return ""
	})
	arrutil.StringsFilter(emCodes)
	url := batch_get_by_code_url + arrutil.StringsJoin(",", arrutil.StringsFilter(emCodes)...)
	resp, err := this.getWithRetry(url, false)
	if err != nil {
		return nil
	}
	byteBody, err := ioutil.ReadAll(resp.Body)
	strBody := string(byteBody)

	resultMap := make(map[string]*api.Stock)
	resultData := gjson.Get(strBody, "data")
	total := resultData.Get("total").Int()
	diffData := resultData.Get("diff")
	for i := 0; i < int(total); i++ {
		stockJson := diffData.Get(strconv.Itoa(i))
		name := stockJson.Get("f14").String()
		marketNum := stockJson.Get("f13").String()
		code := stockJson.Get("f12").String()
		f1 := stockJson.Get("f1").Int()
		f2 := stockJson.Get("f2").String()
		emCode := fromCodeAndMarketNumToEastmoneyCode(code, marketNum)
		if emCode != nil {
			standardCode := emCode.getStandardCode()
			stock := api.Stock{
				Name:  name,
				Code:  standardCode,
				Price: computePrice(int(f1), f2),
			}
			resultMap[standardCode] = &stock
		}
	}
	return resultMap
}

func computePrice(f1 int, f2 string) string {
	splitIdx := len(f2) - f1
	return f2[0:splitIdx] + "." + f2[splitIdx:]
}
